﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mathematics.Parser
{
    public class ExpressionRelationship
    {
        internal ExpressionRelationship(LinkedListNode<Token> node,ExpressionContainer container)
        {
            Node = node;
            Container = container;
        }

        public Domain Domain { get { return Container.Domain; } }
        public ExpressionContainer Container { get; private set; }
        public LinkedListNode<Token> Node { get; private set;}
        public Token Token { get { return Node.Value; } }
        public bool IsProcessed { get; private set; }
        public MathExpression Expression { get; private set; }

        public void Process()
        {
            Expression = ProcessToken();

            IsProcessed = true;
        }


        #region Processing Methods

        private  MathExpression ProcessToken()
        {
            switch (Token.Type)
            {
                case TokenType.Constant:
                    return ProcessConstants();
                case TokenType.Function:
                    return ProcessFunctions();
                case TokenType.Keyword:
                    return ProcessKeyword();
                case TokenType.Operator:
                    return ProcessOperator();
                case TokenType.Variable:
                    return ProcessVariable();
                default:
                    throw new InvalidOperationException("Control token detected in expression");
            }
        }

        private  Variable ProcessVariable()
        {
            return Domain.SafeGetVariable(Token.Text);
        }

        private  Constant ProcessConstants()
        {
            double value;
            if (!double.TryParse(Token.Text, out value))
                throw new ParserException("Constant could not be parsed into a double");

            return new Constant(value);
        }

        private  Function ProcessFunctions()
        {
            throw new NotImplementedException();
        }

        private  MathExpression ProcessKeyword()
        {
            throw new NotImplementedException();
        }

        #region Operator Methods

        private  Operator ProcessOperator()
        {
            switch (Token.Text)
            {
                case "+":
                    return ProcessPlus();
                case "-":
                    return ProcessMinus();
                case "*":
                    return ProcessTimes();
                case "/":
                    return ProcessDivide();
                case "^":
                    return ProcessExponent();
                default:
                    throw new ParserException("Unrecognized operator symbol");
            }
        }

        private  AddOperator ProcessPlus()
        {
        }

        private  AddOperator ProcessMinus()
        {
        }

        private  AddOperator ProcessTimes()
        {
        }

        private  AddOperator ProcessDivide()
        {
        }

        private  AddOperator ProcessExponent()
        {
        }

        #endregion

        #endregion
    }
}
